chain!(e) = e
chain!(e::Expr) = begin
    if e.head == :block
        for i in 2:length(e.args)
            arg = e.args[i]
            if detected(arg, :it)
                symbol = gensym()
                e.args[i - 1] = NumberedLines.without_line_number( e.args[i - 1] ) do line
                    :($symbol = $line)
                end
                e.args[i] = MacroTools.replace(arg, :it, symbol)
            end
        end
    end
    e
end

chain(e) = NumberedLines.with_numbered_lines(e) do e
    MacroTools.postwalk(chain!, copy(e) )
end

export @chain
"""
    @chain(e)

Will `chain` all eligible blocks in `e`, recursively.

It will reinterpret `it` within expressions as the result of the previous
line.

```jldoctest
julia> using ChainRecursive

julia> @chain begin
           1
           vcat(2, it)
       end
2-element Array{Int64,1}:
 2
 1
```

It will recur.
```jldoctest
julia> using ChainRecursive

julia> redundant = @chain begin
           1
           if it == 1
               @chain begin
                   it + 1
                   vcat(it, 3)
               end
           end
       end;

julia> smart = @chain begin
           1
           if it == 1
               it + 1
               vcat(it, 3)
           end
       end;

julia> redundant == smart
true
```
"""
macro chain(args...)
    esc(chain(args...))
end
